﻿using System;
using System.Collections.Generic;

namespace InDepth2Demo.Chapter1314
{
    internal class DynamicDemo
    {
        // 动态地将整数与字符串相加
        public static void Call()
        {
            dynamic items = new List<string> { "First", "Second", "Third" };
            dynamic valueToAdd = 2;
            foreach (dynamic item in items)
            {
                string result = item + valueToAdd;          // string + int 连接
                Console.WriteLine(result);
            }
        }

        // 整数与整数相加
        public static void Call2()
        {
            dynamic items = new List<int> { 1, 2, 3 };
            dynamic valueToAdd = 2;
            foreach (dynamic item in items)
            {
                //string result = item + valueToAdd;        // int + int 相加   （运行会报错：未经处理的异常 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“无法将类型“int”隐式转换为“string””)
                dynamic result = item + valueToAdd;
                Console.WriteLine(result);
            }
        }

        public static void Call3()
        {
            dynamic items = new List<int> { 1, 2, 3 };
            dynamic valueToAdd = 2;
            foreach (dynamic item in items)
            {
                Console.WriteLine(item + valueToAdd);           // 调用以int为参数的重载
            }
        }

        public static void Call4()
        {
            dynamic x = "marson shine";
            string v = x.Substring(6);
            Console.WriteLine(v);
        }

        // 它实际上包含两个动态操作，一个是调用Substring，一个是将结果（编译时为dynamic）动态地（隐式）转换为字符串。
        public static void Call5()
        {
            string text = "text to cut";
            dynamic startIndex = 2;
            string substring = text.Substring(startIndex);
        }

        static void Execute(dynamic x, string y)
        {
            Console.WriteLine("dynamic, string");
        }
        static void Execute(dynamic x, object y)
        {
            Console.WriteLine("dynamic, object");
        }

        public static void Call6()
        {
            object text = "text";
            dynamic d = 10;
            Execute(d, text);       // 打印"dynamic, object"

            dynamic d2 = "text2";
            Execute(d, d2);         // 打印"dynamic, string"

            // text 其编译时类型为object，但执行时的值为字符串引用。对Execute的调用是动态的，因为我们使用了动态变量d作为一个参数，但重载决策使用了text的静态类型， 因此结果为dynamic、object。
            // 如果text变量也声明为dynamic，则将使用另一个重载。

            // 言外之意，如果无法得到参数的编译时类型（尽管编译时text仍然为object，但由于它声明为dynamic，在编译后的代码中，该参数所对应的CSharpArgumentInfoFlags的枚举值为None，即绑定时不附加编译时信息。
            // 而如果声明为object，对应的CSharpArgumentInfoFlags枚举值为UseCompileTimeType，即在绑定时使用参数的编译时类型。可参考代码清单14-17），就使用执行时类型（即string）
        }

        public static void Call7()
        {
            Base receiver = new Derived();
            dynamic d = "text";
            receiver.Execute(d);            //打印"object"
        }

        void Execute<T>(T first, T second, string other) where T : struct
        {

        }

        public static void Call8()
        {
            dynamic guid = Guid.NewGuid();
            //Execute(10, 0, guid);
            //Execute(10, false, guid);
            //Execute("hello", "hello", guid);
        }
    }

    class Base
    {
        public void Execute(object x)
        {
            Console.WriteLine("object");
        }
    }

    class Derived : Base
    {
        public void Execute(string x)
        {
            Console.WriteLine("string");
        }
    }

}
